// Copyright (c) 2009 Mike Haight, Andy Kipp
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include "Scene.h"

using namespace HandBanana::Core;
using namespace HandBanana::Game;
using namespace HandBanana::Utilities;
using namespace HandBanana::Utilities::Xml;

Scene::Scene(void) 
{
}


Scene::~Scene(void)
{
}


std::wstring Scene::Name(void) const
{
    return mName;
}


Size Scene::Size(void) const
{
    return mSize;
}


void Scene::AddLayer(const std::wstring &argName, Layer *argLayer)
{
    delete argLayer;
}


//List<WorldObject^>^ World::GetObjects(Coordinates::Rectangle argRectangle)
//{
//    List<WorldObject^>^ objects = gcnew List<WorldObject^>();
//    for each (WorldObject^ obj in mObjects.Values)
//        if (argRectangle.Contains(obj->Location))
//            objects->Add(obj);
//    return objects;
//}

void Scene::ReadXml(const XmlReader& argReader)
{
    // Log
    Logger::Debug(L"Deserializing Scene.");

    // Create XmlDocument
    XmlDocument* doc = new XmlDocument();

    // Load Document
    doc->Load(argReader);

    // Get Scene Element
    XmlElement* sceneElement = doc->GetDocumentElement();

    // Get Scene Element Attributes
    mName = sceneElement->GetAttribute(L"Name")->GetValue();
    mSize.Height = (float)wstrparseint(sceneElement->GetAttribute(L"Height")->GetValue());
    mSize.Width= (float)wstrparseint(sceneElement->GetAttribute(L"Width")->GetValue());

    // Read Scene Element
    {
        XmlNode *childNode;
        for(childNode = sceneElement->GetFirstChild(); childNode != NULL; childNode = sceneElement->GetNextChild())
        {
            if (childNode->GetType() == Element)
            {
                XmlElement* childElement = (XmlElement*)childNode;

                if (childElement->GetName() == L"Layer")
                {
                    // Write XmlElement to stream
                    std::wstringstream stream;
                    XmlWriter writer(&stream);
                    writer.WriteElement(childElement);

                    // Create Layer
                    Layer* layer = new Layer();

                    // Create XmlReader
                    XmlReader reader(&stream);
                    layer->ReadXml(reader);

                    // Add Layer to scene
                    AddLayer(layer->Name(), layer);
                }
                else if (childElement->GetName() == L"Monster")
                {
                }
                else 
                {
                    throw XmlException(L"Unknown Element: \"" + childElement->GetName() + L"\"");
                }
            }
        }
    }

    // Delete XmlDocument
    SAFE_DELETE(doc);
}


void Scene::WriteXml(const XmlWriter& argWriter)
{
}


Scene* Scene::Load(const std::wstring& argFileName)
{
    Scene* scene;

    // Log
    Logger::Info(L"Loading Scene: \"" + argFileName + L"\".");

    try
    {
        // Create Scene
        scene = new Scene();

        // Create input file stream
        std::wifstream file(argFileName.c_str());

        // Create Parser from input file stream
        const XmlReader parser(&file);

        // Deserialize Scene
        scene->ReadXml(parser);

        // Close File
        file.close();
    } 
    catch (XmlException ex)
    {
        Logger::Error(L"Error reading Scene XML.");
    }

    return scene;
}